<!--
  Copyright 2012-2019 the original author or authors.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- clearfix is needed for smaller screens where gt-config-return-link is floated  -->
<div class="clearfix">
  <a class="gt-config-return-link"
     href="config/instrumentation-list{{agentQueryString()}}">
    Return to list
  </a>
</div>
<div class="card">
  <div class="card-header">
    <h2 ng-class="{'gt-lighten-font': !loaded && !httpError}">
      Instrumentation
      <span class="d-inline-block gt-separator">
        |
      </span>
      <span style="font-size: 24px; word-wrap: break-word;">{{heading}}</span>
    </h2>
  </div>
  <div class="card-body">
    <div ng-include src="'template/gt-loading-overlay.html'"></div>
    <div ng-include src="'template/gt-http-error-overlay.html'"></div>
    <div ng-if="agentNotConnected" class="alert alert-warning">
      Limited functionality since agent is not currently connected
    </div>
    <form gt-form-autofocus-on-first-input
          name="formCtrl"
          novalidate>
      <fieldset class="gt-fieldset">
        <legend class="gt-legend">
          What method(s) to instrument
        </legend>
        <div class="form-group row">
          <label class="col-xl-3 gt-form-label-xl"
                 for="className{{$id}}">
            Class name
          </label>
          <div class="col-xl-9">
            <input type="text"
                   class="form-control"
                   ng-model="config.className"
                   ng-required="true"
                   ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                   uib-typeahead="suggestion for suggestion in classNames($viewValue)"
                   typeahead-on-select="onSelectClassName()"
                   typeahead-wait-ms="5"
                   name="className"
                   id="className{{$id}}"
                   style="max-width: 40em; display: inline-block">
            <div class="gt-invalid-required-feedback">
              This is required.
            </div>
            <div gt-spinner
                 gt-spinner-inline="true"
                 gt-show="showClassNameSpinner"
                 gt-no-delay="true"
                 class="gt-inline-spinner">
            </div>
            <div class="help-block">
              The class or interface containing the method(s) to instrument.
            </div>
          </div>
        </div>
        <div class="form-group row">
          <label class="col-xl-3 gt-form-label-xl"
                 for="methodName{{$id}}">
            Method name
          </label>
          <div class="col-xl-9">
            <input type="text"
                   class="form-control"
                   ng-model="config.methodName"
                   ng-required="true"
                   ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                   uib-typeahead="suggestion for suggestion in methodNames($viewValue)"
                   typeahead-on-select="onSelectMethodName()"
                   typeahead-wait-ms="5"
                   ng-blur="onBlurMethodName()"
                   name="methodName"
                   id="methodName{{$id}}"
                   style="max-width: 40em; display: inline-block;">
            <div class="gt-invalid-required-feedback">
              This is required.
            </div>
            <div gt-spinner
                 gt-spinner-inline="true"
                 gt-show="showMethodNameSpinner"
                 gt-no-delay="true"
                 class="gt-inline-spinner">
            </div>
            <div class="help-block">
              The method(s) to instrument.
              All overriding methods will also be instrumented
              (including all implementations of the method if the class above is an interface).
            </div>
            <div class="help-block">
              The wildcard <code>*</code> is supported anywhere in the method name.
              Multiple method names (including multiple method names with the wildcard <code>*</code> in them) can be
              listed with the <code>|</code> separator between them.
            </div>
          </div>
        </div>
        <fieldset class="form-group">
          <div class="row">
            <legend class="col-xl-3 gt-check-legend-xl">
              Method signature
            </legend>
            <div class="col-xl-9">
              <div class="form-check"
                   ng-repeat="methodSignature in methodSignatures">
                <label class="form-check-label">
                  <!-- need $parent.selectedSignature since ng-repeat creates a new scope
                    see https://github.com/angular/angular.js/issues/1100 -->
                  <input class="form-check-input"
                         type="radio"
                         name="selectedMethodSignature"
                         ng-model="$parent.selectedMethodSignature"
                         ng-value="methodSignature"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation">
                  {{methodSignatureText(methodSignature)}}
                  <div class="gt-red"
                       ng-if="methodSignature.notAvailable">
                    Warning: this signature could not be found in the runtime classpath
                  </div>
                </label>
              </div>
              <div class="help-block">
                Only the method name and parameter types are used when evaluating what to instrument
                (the return type and access modifiers are ignored).
              </div>
            </div>
          </div>
        </fieldset>
      </fieldset>
      <fieldset class="gt-fieldset">
        <legend class="gt-legend">
          What to capture
        </legend>
        <fieldset class="form-group">
          <div class="row">
            <legend class="col-xl-3 gt-check-legend-xl">
              What to capture
            </legend>
            <div class="col-xl-9">
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.captureKind"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="transaction">
                  Transaction
                </label>
              </div>
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.captureKind"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="trace-entry">
                  Trace entry
                </label>
              </div>
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.captureKind"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="timer">
                  Timer
                </label>
              </div>
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.captureKind"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="other">
                  Optional transaction overrides only
                </label>
              </div>
              <div class="help-block">
                A transaction defines the capture point boundary for a new request or background operation.
              </div>
              <div class="help-block">
                A trace entry is a timer plus it captures a message on each invocation of the above method(s) to produce
                the data in the <em>trace entries</em> section when viewing an individual trace.
              </div>
              <div class="help-block">
                A timer captures the total time and count of the above method(s) to produce the data in the
                <em>breakdown</em> section on the <a href="transaction/average{{agentQueryString()}}">average response
                time page</a>, and the data in the <em>breakdown</em> section when viewing an individual trace (on the
                <a href="transaction/traces{{agentQueryString()}}">slow traces</a> or
                <a href="error/traces{{agentQueryString()}}">error traces</a> pages).
              </div>
            </div>
          </div>
        </fieldset>
        <div gt-form-group
             gt-label="Transaction type"
             gt-model="config.transactionType"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="40em"
             gt-required="captureKindTransaction"
             ng-if="captureKindTransaction">
          <div class="help-block">
            The transaction type is used for aggregation and filtering.
          </div>
          <div class="help-block">
            This can be one of the current transaction types ({{agentRollup.transactionTypes.join(', ')}})
            or a new transaction type.
          </div>
        </div>
        <div gt-form-group
             gt-label="Transaction name"
             gt-model="config.transactionNameTemplate"
             gt-required="captureKindTransaction"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="40em"
             ng-if="captureKindTransaction">
          <div class="help-block">
            The transaction name is used for aggregation and filtering.
          </div>
          <div ng-non-bindable
               class="help-block">
            This is a template which can be populated with values from the method invocation.
            The same rules apply as for the trace headline (see below), except that the return value <code>{{_}}</code>
            cannot be used.
          </div>
        </div>
        <div gt-form-group
             gt-type="textarea"
             gt-label="{{captureKindTransaction ? 'Trace headline' : 'Trace entry'}}"
             gt-model="config.traceEntryMessageTemplate"
             gt-required="showTraceEntry"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="40em"
             gt-rows="2"
             ng-if="showTraceEntry">
          <div class="help-block">

          </div>
          <div ng-non-bindable
               class="help-block">
            This is a template which can be populated with values from the method invocation:
            <ul>
              <li>
                <code>{{0}}</code>, <code>{{1}}</code>, ... resolve to the method parameters
              </li>
              <li>
                <code>{{this}}</code> resolves to the object that the method is invoked on (except for static methods)
              </li>
              <li>
                <code>{{_}}</code> resolves to the return value (if not void)
              </li>
              <li>
                <code>{{methodName}}</code> resolves to the method name, which can be useful if <code>*</code> or
                <code>|</code> are used to define the method name above
              </li>
            </ul>
          </div>
          <div class="help-block"
               ng-non-bindable>
            Nested paths are resolved as well, e.g. <code>{{0.size}}</code> and <code>{{this.class.name}}</code>.
            If a path resolves to null at any point, then the entire path will resolve to null.
            The final resolved value is rendered into the template using
            <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#valueOf-java.lang.Object-">
              String.valueOf()
            </a>.
            If the final resolved value is a byte array, it will be rendered as hex, or you can specify a charset to
            decode it, e.g. <code>{{0.someBytes|charset:UTF-8}}</code> or <code>{{0.someBytes|charset:default}}</code>
            to use the default (platform) charset.
          </div>
        </div>
        <div gt-form-group
             gt-label="Timer name"
             gt-model="config.timerName"
             gt-pattern="/^[a-zA-Z0-9 ]*$/"
             gt-required="loaded && showTimer"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="20em"
             ng-if="showTimer">
          <div class="help-block">
            Multiple instrumentation definitions can share the same timer name,
            in which case their timers are aggregated together.
          </div>
        </div>
        <fieldset class="form-group"
                  ng-if="captureKindTransaction">
          <div class="row">
            <legend class="col-xl-3 gt-check-legend-xl">
              What to do if already in a transaction
            </legend>
            <div class="col-xl-9">
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.alreadyInTransactionBehavior"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="capture-trace-entry">
                  Capture a trace entry (as part of the existing transaction)
                </label>
              </div>
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.alreadyInTransactionBehavior"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="capture-new-transaction">
                  Capture a new transaction
                </label>
              </div>
              <div class="form-check">
                <label class="form-check-label">
                  <input class="form-check-input"
                         type="radio"
                         ng-model="config.alreadyInTransactionBehavior"
                         ng-disabled="!agentRollup.permissions.config.edit.instrumentation"
                         value="do-nothing">
                  Do nothing
                </label>
              </div>
            </div>
          </div>
        </fieldset>
        <div gt-form-group
             gt-label="Stack trace threshold"
             gt-model="config.traceEntryStackThresholdMillis"
             gt-number="true"
             gt-pattern="pattern.integer"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="7em"
             gt-addon="milliseconds"
             ng-if="showTraceEntryStackThresholdMillis">
          <div class="help-block">
            Any trace entry that exceeds this threshold will have a stack trace captured and attached to it
            in order to help identify the source of this trace entry.
            Empty means never capture a stack trace for this trace entry.
          </div>
        </div>
        <div gt-form-group
             gt-type="checkbox"
             gt-label="Self nesting"
             gt-checkbox-label="Capture self nested trace entries"
             gt-model="config.traceEntryCaptureSelfNested"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             ng-if="showTraceEntryCaptureSelfNested">
          <div class="help-block">
            If checked, and this custom instrumentation is encountered beneath itself or beneath another pointcut that
            shares the same timer name, a nested trace entry <em>will</em> be captured.
            This can sometimes lead to a lot of extra noise, e.g. in a fairly common case where the
            custom instrumentation matches several overloaded methods that cascade to each other.
          </div>
        </div>
      </fieldset>
      <fieldset class="gt-fieldset">
        <legend class="gt-legend">
          Optional transaction overrides
        </legend>
        <div gt-form-group
             gt-label="Transaction type"
             gt-model="config.transactionType"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="40em"
             ng-hide="captureKindTransaction">
          <div class="help-block">
            The transaction type is used for aggregation and filtering.
          </div>
          <div class="help-block">
            This can be one of the current transaction types ({{agentRollup.transactionTypes.join(', ')}})
            or a new transaction type.
          </div>
          <div class="help-block">
            The value provided will override the transaction type for the containing transaction.
            If the transaction type is overridden more than once for a given transaction,
            the first non-null/non-empty value will be used.
          </div>
        </div>
        <div gt-form-group
             gt-label="Transaction name"
             gt-model="config.transactionNameTemplate"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="40em"
             ng-hide="captureKindTransaction">
          <div class="help-block">
            The transaction name is used for aggregation and filtering.
          </div>
          <div class="help-block">
            The value provided will override the transaction name for the containing transaction.
            If the transaction name is overridden more than once for a given transaction,
            the first non-null/non-empty value will be used.
          </div>
          <div ng-non-bindable
               class="help-block">
            This is a template which can be populated with values from the method invocation:
            <ul>
              <li>
                <code>{{0}}</code>, <code>{{1}}</code>, ... resolve to the method parameters
              </li>
              <li>
                <code>{{this}}</code> resolves to the object that the method is invoked on (except for static methods)
              </li>
              <li>
                <code>{{methodName}}</code> resolves to the method name, which can be useful if <code>*</code> or
                <code>|</code> are used to define the method name above
              </li>
            </ul>
          </div>
          <div ng-non-bindable
               class="help-block">
            Nested paths are resolved as well, e.g. <code>{{0.size}}</code> and <code>{{this.class.name}}</code>.
            If a path resolves to null at any point, then the entire path will resolve to null.
            The final resolved value is rendered into the template using
            <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#valueOf-java.lang.Object-">
              String.valueOf()
            </a>.
            If the final resolved value is a byte array, it will be rendered as hex, or you can specify a charset to
            decode it, e.g. <code>{{0.someBytes|charset:UTF-8}}</code> or <code>{{0.someBytes|charset:default}}</code>
            to use the default (platform) charset.
          </div>
        </div>
        <div gt-form-group
             gt-label="Slow trace threshold"
             gt-model="config.transactionSlowThresholdMillis"
             gt-number="true"
             gt-pattern="pattern.integer"
             gt-disabled="!agentRollup.permissions.config.edit.instrumentation"
             gt-width="7em"
             gt-addon="milliseconds">
          <div class="help-block">
            This will override the slow threshold for the containing transaction.
            The value can be smaller than the global slow threshold to force slow transaction traces to be stored more
            often, or larger to force slow transaction traces to be stored less often.
            If the slow threshold is overridden more than once for a given transaction,
            the smallest override value will be used.
          </div>
        </div>
      </fieldset>
      <div class="form-group row gt-form-buttons-below-fieldset">
        <div class="offset-xl-3 col-xl-9">
          <div gt-button-group>
            <div gt-button
                 gt-label="{{config.version ? 'Save changes' : 'Add'}}"
                 gt-click="save(deferred)"
                 gt-validate-form="formCtrl"
                 ng-if="agentRollup.permissions.config.edit.instrumentation"
                 class="d-inline-block">
            </div>
            <div gt-button
                 ng-if="config.version"
                 gt-label="Delete"
                 gt-click="delete(deferred)"
                 gt-btn-class="btn-danger"
                 ng-if="agentRollup.permissions.config.edit.instrumentation"
                 class="d-inline-block">
            </div>
            <div gt-button
                 gt-label="Export to JSON"
                 gt-click="exportToJson(deferred)"
                 gt-validate-form="formCtrl"
                 gt-btn-class="btn-secondary"
                 class="d-inline-block">
            </div>
          </div>
        </div>
      </div>
    </form>
  </div>
</div>
<div class="modal"
     role="dialog"
     tabindex="-1"
     id="jsonExportModal">
  <div class="modal-dialog modal-dialog-centered gt-modal-dialog-md"
       role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h3 class="modal-title">
          Instrumentation JSON
          <span class="fas fa-clipboard gt-clip"
                style="font-size: 14px; vertical-align: 5px; position: inherit; margin-left: 5px;"></span>
        </h3>
        <button type="button"
                class="close"
                data-dismiss="modal"
                aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body" style="padding-top: 20px;">
        <pre id="jsonExport" style="white-space: pre-wrap; word-wrap: break-word;">{{jsonExport}}</pre>
      </div>
    </div>
  </div>
</div>
<!-- each page with confirmation dialog needs its own confirmation dom so that it is deleted on $destroy -->
<div ng-include="'template/gt-confirmation.html'"></div>
